﻿using Common;
using Common.Communications;
using Common.Helpers;
using Common.Model;
using Newtonsoft.Json;
using RollerControllerService.Enums;
using RollerControllerService.Model;
using Serilog;

namespace RollerControllerService
{
    /// <summary>
    /// 滚筒控制服务
    /// </summary>
    public class TransferRollerService
    {
        private RollerSettingModel rcsServiceComInfo = new RollerSettingModel();

        private ModbusCommunication modbusCommunication;

        #region 事件
        public event Func<string, Task> ResultRollerInfoChange;
        #endregion

        #region 构造
        public TransferRollerService()
        {
            var flag = InitSettingInfo();
            if (flag)
            {
                CreatModebusComAsync();
            }
        }
        #endregion

        #region 初期数据
        private bool InitSettingInfo()
        {
            var info = AppSetting.Instance.settingSingleModels.FirstOrDefault(s => s.SettingType == ConstString.RollerControlKey);
            if (info is null)
            {
                Log.Error($"滚筒通信数据未配置");
                return false;   
            }
            try
            {
                if (info.ModelType != typeof(RollerSettingModel))
                {
                    Log.Error($"Rcs服务通信参数配置错误");
                    return false;
                }
                var infos = JsonConvert.DeserializeObject(info.Values, info.ModelType);
                rcsServiceComInfo = infos as RollerSettingModel;
                return true;
            }
            catch (Exception ex)
            {
                Log.Error($"Rcs服务通信参数读取异常");
                return false;
            }
        }

        private async Task CreatModebusComAsync()
        {

            modbusCommunication = new ModbusCommunication(rcsServiceComInfo.Ip, int.Parse(rcsServiceComInfo.Port));
            var flag = await modbusCommunication.ConnectAsync();
            if (!flag)
            {
                Log.Error($"modbus通信创建失败!");
            }
        }
        #endregion

        public async Task WcsMsgProcessAsync(string reqCode,string msg)
        {
            var info = JsonConvert.DeserializeObject<RollerOpticalModel>(msg);
            if (info is null)
            {
                return;
            }
            switch (info.modbusFunCode)
            {
                case ConstString.Writ_03:
                    await WriteProcessAsync(reqCode,info.rollerAction);
                    break;
                case ConstString.Read_04:
                    await ReadProcessAsync(reqCode);
                    break;
            }
        }

        private async Task ReadProcessAsync(string reqCode)
        {
            var info = await ReadInputRegisterAsync();
            OpticalInfoModel data = new OpticalInfoModel();
            data.funCode = ConstString.RollerCode;
            data.EqCode = AppSetting.Instance.EqCode;
            data.type = Common.Enums.OpticalEnums.OpticalMsgType.Roller;
            data.number = reqCode;
            data.data = JsonConvert.SerializeObject(info);
            data.dataLen = data.data.Length;
            var sendMsg = JsonConvert.SerializeObject(data) + ConstString.Termination;

            ResultRollerInfoChange?.Invoke(sendMsg);
        }

        private async Task WriteProcessAsync(string reqCode,RollerState value)
        {
           var flag = await WritHoldingRegisterAsync(value);
            if (!flag)
            {
                Log.Error($"modbus写入失败{reqCode}");
                return;
            }
            var info = await ReadInputRegisterAsync();
            OpticalInfoModel data = new OpticalInfoModel();
            data.funCode = ConstString.RollerCode;
            data.EqCode = AppSetting.Instance.EqCode;
            data.type = Common.Enums.OpticalEnums.OpticalMsgType.Roller;
            data.number = reqCode;
            data.data = JsonConvert.SerializeObject(info);
            data.dataLen = data.data.Length;
            var sendMsg = JsonConvert.SerializeObject(data) + ConstString.Termination;

            ResultRollerInfoChange?.Invoke(sendMsg);
        }

        /// <summary>
        /// 写入滚筒状态
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        private async Task<bool> WritHoldingRegisterAsync(RollerState value)
        {
            return await Task.Run(() => 
            {
                if (modbusCommunication is null)
                {
                    return false;
                }
                var data = value as short?;
                if (!data.HasValue)
                {
                    return false;
                }
                modbusCommunication.WriteSingleRegister(1, 0, data.Value);
                return true;
            });
        }
        /// <summary>
        /// 读取滚筒信息
        /// </summary>
        /// <returns></returns>
        private async Task<RollerInfoModel> ReadInputRegisterAsync()
        {
            return await Task.Run(() => 
            {
                RollerInfoModel rollerInfo = new RollerInfoModel();
                if (modbusCommunication is null)
                {
                    return rollerInfo;
                }
                
                var infos = modbusCommunication.ReadInputRegisters(1, 0, 4);
                if (infos is not null)
                {
                    rollerInfo.rollerState = (RollerState)infos[0];
                    rollerInfo.materialState = (MaterialState)infos[1];
                    short[] values = new short[2];
                    values[0] = infos[2];
                    values[1] = infos[3];
                    rollerInfo.waring = ModbusHelper.GetHexString(values, 0);
                }
                return rollerInfo;
            });
            
        }
    }
}
